/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.bookmarksframework.core.history
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	import mx.collections.IViewCursor;
	
	import org.bookmarksframework.core.Path;
	
	[Event(name="change", type="flash.events.Event")]
	
	/**
	 *  TODO: improve
	 */
	public class History extends EventDispatcher implements IHistory
	{
		protected var history:ArrayCollection;
		
		protected var cursor:IViewCursor;
		
		public function History()
		{
			super();
			
			history = new ArrayCollection();
			cursor = history.createCursor();
		}
		
		[Bindable("collectionChanged")]
		public function get collection():ArrayCollection
		{
			return new ArrayCollection(history.toArray());
		}
		
		public function store(value:*):void
		{
			if (!history.length)
			{
				history.addItem(new HistoryItem(value));
				cursor.movePrevious();
			}
			else if (cursor.current)
			{
				cursor.moveNext();
				
				while (cursor.current)
					cursor.remove();
				
				cursor.insert(new HistoryItem(value));
				cursor.movePrevious();
			}
			
			dispatchEvent(new Event("collectionChanged"));
			dispatchEvent(new Event("historyChanged"));
		}
		
		public function forward():void
		{
			var result:Boolean = internalForward();
			
			if (result)
				dispatchChange();
		}
		
		public function back():void
		{
			var result:Boolean = internalBack();
			
			if (result)
				dispatchChange();
		}
		
		[Bindable("historyChanged")]
		public function get current():*
		{
			return cursor.current as HistoryItem;
		}
		
		[Bindable("historyChanged")]
		public function get next():*
		{
			var result:HistoryItem = null;
			
			if (cursor.current)
			{
				if (cursor.moveNext())
					result = cursor.current as HistoryItem;
				
				cursor.movePrevious();
			}
			
			return result;
		}
		
		[Bindable("historyChanged")]
		public function get previous():*
		{
			var result:HistoryItem = null;
			
			if (cursor.current)
			{
				if (cursor.movePrevious())
					result = cursor.current as HistoryItem;
				
				cursor.moveNext();
			}
			
			return result;
		}
		
		public function go(value:int):void
		{
			var result:Boolean = false;
			var steps:Number = Math.abs(value);
			
			for (var i:int = 0; i < steps; ++i)
			{
				result = (value > 0) ? 
					internalForward() : internalBack();
				
				if (!result)
					break;
			}
			
			dispatchChange();
		}
		
		public function get length():Number
		{
			return history.length;
		}
		
		public function destroy():void
		{
			history = null;
			cursor = null;
		}
		
		protected function internalForward():Boolean
		{
			var result:Boolean = cursor.moveNext();
			if (!result) cursor.movePrevious();
			
			return result;
		}
		
		protected function internalBack():Boolean
		{
			var result:Boolean = cursor.movePrevious();
			if (!result) cursor.moveNext();
			
			return result;
		}
		
		protected function dispatchChange():void
		{
			dispatchEvent(new Event("historyChanged"));
			dispatchEvent(new Event(Event.CHANGE));
		}
		
	}
}